/***************************************
 * Created and Edited by OceanMaster
 * to implement the function of nearby
 * resources 
 ***************************************/

package com.ushahidi.android.app;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.*;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.*;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.SeekBar.OnSeekBarChangeListener;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;
import com.ushahidi.android.app.ChangeLoc.MapMarker;
import com.ushahidi.android.app.ChangeLoc.OneTimeDeviceLocationListener;
import com.ushahidi.android.app.data.HandleXml;
import com.ushahidi.android.app.data.IncidentsData;
import com.ushahidi.android.app.data.ResourceData;
import com.ushahidi.android.app.data.UshahidiDatabase;
import com.ushahidi.android.app.net.AroundMeNetRequest;
import com.ushahidi.android.app.util.Util;

import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class AroundMeMap extends MapActivity
{
    private MapView                    mapView               = null;

    private static final int           HOME                  = Menu.FIRST + 1;

    private static final int           LIST_INCIDENT         = Menu.FIRST + 2;

    private static final int           INCIDENT_ADD          = Menu.FIRST + 3;

    private static final int           INCIDENT_REFRESH      = Menu.FIRST + 4;

    private static final int           SETTINGS              = Menu.FIRST + 5;

    private static final int           ABOUT                 = Menu.FIRST + 6;

    private static final int           GOTOHOME              = 0;

    private static final int           ADD_INCIDENTS         = 1;

    private static final int           LIST_INCIDENTS        = 2;

    private static final int           REQUEST_CODE_SETTINGS = 1;

    private static final int           REQUEST_CODE_ABOUT    = 2;

    private static final int           DIALOG_MESSAGE        = 0;

    private static double              latitude;

    private static double              longitude;

    private static boolean				mapmoved=false;
    // Oceanmaster
    private static double              holder_latitude;

    private static double              holder_longitude;
    // end

    public static Geocoder             mGc;

    private static List<IncidentsData> tmpResourcesPile;
    private static List<IncidentsData> NearbyResources;
    // OceanMaster Generally, ResourceData is the same as IncidentsData.....
    // But IncidentsData is supported by library

    private Handler                    mHandler;

    private Bundle                     extras;

    private String                     reportLatitude;

    private String                     reportLongitude;

    private String                     reportTitle;

    private String                     reportDescription;

    public List<Drawable>              markers;

    // OceanMaster
    // private boolean GPSUpdated = false;
    // OceanMaster, used to mark if GPS is updated
    private int                        GPSCount              = 0;
    // How many times GPS data has been updated.
    // 1 time per second
    private final int                  updateCycle           = 20;
    // The cycle of Gps drawing map.
    // Add end

    // --------------------------
    // OceanMaster
    private ToggleButton               FollowButton;
    private ToggleButton               SatelliteButton;
    private Button 					   RedoSearchButton;
    private SeekBar                    RadiusBar;
    private TextView                   RadiusText;

    private boolean                    follow                = true;
    //private static double              NearByRadius          = 1.5;

    private static int catid = -1;	
    // in mile

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
	super.onCreate(savedInstanceState);
	// Log.v("Oceanmaster", "test1");
	requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
	// Log.v("Oceanmaster", "test2");
	setContentView(R.layout.aroundme_map);

	if(getIntent().hasExtra("catid"))
	    catid = getIntent().getExtras().getInt("catid");
	else
	    catid = -1;
	
	Log.v("Oceanmaster", "cat id passed in is "+catid);
	
	LoadMarkers();

	mapView = (MapView) findViewById(R.id.map);
	mapView.setSatellite(false);
	tmpResourcesPile = new ArrayList<IncidentsData>();
	mHandler = new Handler();
	// self
	mGc = new Geocoder(this, Locale.US);
	extras = this.getIntent().getExtras();

	RadiusText = (TextView) findViewById(R.id.RadiusText);
	RedoSearchButton= (Button)findViewById(R.id.RedoSearchButton);
	RedoSearchButton.setOnClickListener(new OnClickListener()
	{

		@Override
		public void onClick(View v) {
			GeoPoint mapcenter=mapView.getMapCenter();
			mapView.postInvalidate();
		    if (mapcenter != null)
		    {
			holder_latitude = mapcenter.getLatitudeE6()/10E5;
			holder_longitude = mapcenter.getLongitudeE6()/10E5;
			ClearMap();
			updateNearBy();
			GPSCount--;
		    }
		}}
			);
	FollowButton = (ToggleButton) findViewById(R.id.FollowMeButton);
	FollowButton.setOnCheckedChangeListener(new OnCheckedChangeListener()
	{
	    @Override
	    public void onCheckedChanged(CompoundButton arg0, boolean checked)
	    {
		follow = checked;
	    }
	});

	SatelliteButton = (ToggleButton) findViewById(R.id.SateliteButton);
	SatelliteButton
	        .setOnCheckedChangeListener(new OnCheckedChangeListener()
	        {
		    @Override
		    public void onCheckedChanged(CompoundButton arg0,
		            boolean checked)
		    {
		        mapView.setSatellite(checked);
		    }
	        });

	RadiusBar = (SeekBar) findViewById(R.id.RadiusBar);
	RadiusBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
	{
	    @Override
	    public void onProgressChanged(SeekBar seekBar, int progress,
		    boolean fromUser)
	    {
		// TODO Auto-generated method stub
	    //Log.v("Oceanmaster", "Radius Bar Changed : "+progress);
		UshahidiPref.NearByRadius = progress * 0.1;
		RadiusText.setText(progress / 10 + "." + progress % 10);
	    }

	    @Override
	    public void onStartTrackingTouch(SeekBar seekBar)
	    {
		// TODO Auto-generated method stub
	    }

	    @Override
	    public void onStopTrackingTouch(SeekBar seekBar)
	    {
		ZoomAccordingToRadius(UshahidiPref.NearByRadius);
		updateNearBy();
		GPSCount = 0; // Force Map to update
		Log.v("Oceanmaster", "Radius Bar Changed Over");
	    }
	});
	
	readyLocationService();// make sure current location and pick right
	                       // detail level
	mapView.setBuiltInZoomControls(false);
	//ConfigAccordingToRadius(1.5);
	mapView.getController().setZoom(15);
    }

    //---------------------------------
    //	Utility used to calculate Mile,
    //	Meter and Degree.
    //---------------------------------
    
    private void ZoomAccordingToRadius(double radiusInMile)
    {
	//radius 's unit is mile
	int latSpanE6 = (int) ( Util.MilesToLatitudeDegrees(radiusInMile) * 1000000.0 );
	int lonSpanE6 = (int) ( Util.MilesToLongitudeDegree(radiusInMile, holder_latitude) * 1000000.0 );
	mapView.getController().zoomToSpan(latSpanE6*3, lonSpanE6*3);
	//mapView.getController().setZoom(15);
    }

    @Override
    protected boolean isRouteDisplayed()
    {
	return (false);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
	Log.v("Oceanmaster", "Key Down : " + keyCode);
	if (keyCode == KeyEvent.KEYCODE_I)
	{
	    // Zoom not closer than possible
	    mapView.getController().zoomIn();
	    return true;
	}
	else if (keyCode == KeyEvent.KEYCODE_O)
	{
	    // Zoom not farer than possible
	    mapView.getController().zoomOut();
	    return true;
	}
	else if (keyCode == KeyEvent.KEYCODE_T)
	{
	    // Switch to satellite view
	    mapView.setSatellite(true);
	    return true;
	}
	else if (keyCode == KeyEvent.KEYCODE_M)
	{
	    // Switch to map view
	    mapView.setSatellite(false);
	    return true;
	}
	return super.onKeyDown(keyCode, event);
    }
    public static List<IncidentsData> QueryNearBy()
    {
    	tmpResourcesPile.clear();
    	String results=null;
    	if(catid != -1)
    	{
    	    if( AroundMeNetRequest.getNearByResourceFromWeb_XML(UshahidiPref.NearByRadius,
    	        true, holder_latitude, holder_longitude,catid+""))
    	    	results=UshahidiPref.resourceResponse;
    	}
    	else
    	{ 
    	   if( AroundMeNetRequest.getNearByResourceFromWeb_XML(UshahidiPref.NearByRadius,
    		        true, holder_latitude, holder_longitude))
    		   results=UshahidiPref.resourceResponse ;
    	}
    	tmpResourcesPile=HandleXml.processResourceXml_ReturnIncident(results);
    	return tmpResourcesPile;
    }
    // Query nearby resources according to Current Position and radius
    // Directly use online api
    // Modified by OceanMaster
/*
    public static List<IncidentsData> QueryNearBy()
    {
	// TODO: change to web based data

	tmpResourcesPile.clear();// by OceanMaster
	
	JSONArray results;
	if(catid != -1)
	    results = AroundMeNetRequest.getNearByResourceFromWeb(UshahidiPref.NearByRadius,
	        true, holder_latitude, holder_longitude,catid+"");
	else
	    results = AroundMeNetRequest.getNearByResourceFromWeb(UshahidiPref.NearByRadius,
		        true, holder_latitude, holder_longitude);

	if (results == null || results.length()==0)// 没有结果
	    return tmpResourcesPile;

	String title;
	String description;
	String location;
	String categories;
	String thumbnail;
	String image;

	try
	{

	    for (int i = 0; i < results.length(); i++)
	    {
		JSONObject cursor = results.optJSONObject(i);

		JSONObject resource = cursor.getJSONObject("resource");
		JSONArray cates = cursor.getJSONArray("categories");

		IncidentsData incidentData = new IncidentsData();
		tmpResourcesPile.add(incidentData);

		int id = resource.getInt("resourceid");
		incidentData.setIncidentId(id);

		title = Util.capitalizeString(resource
		        .getString("resourcetitle"));
		incidentData.setIncidentTitle(title);

		description = resource.getString("resourcedescription");
		incidentData.setIncidentDesc(description);

		categories = "";
		for (int j = 0; j < cates.length(); j++)
		    categories += cates.optJSONObject(j)
			    .getJSONObject("category").getString("title");
		incidentData.setIncidentCategories(categories);

		// Updated to here!!!s
		location = resource.getString("locationname");
		incidentData.setIncidentLocLongitude(location);
		
		Util.joinString("Date: ", resource.getString("resourcedate"));
		incidentData
		        .setIncidentDate(resource.getString("resourcedate"));
		
		////////////////////////////////////////
		 //process media by yujie chen
		 JSONArray mediaList = cursor.getJSONArray("media");
		 for(int j = 0; j < mediaList.length(); j++)
		 {
			 JSONObject mediaNode= mediaList.optJSONObject(j);
			 JSONArray mediaThumbList= mediaNode.getJSONArray("thumb");
			 if(mediaThumbList.length()!=0)
			 {
				UshahidiService.mNewResourceThumbnails
					.add(mediaThumbList.getJSONObject(0).getString("thumb"));
				File thumbnailFilename = new File(
						(mediaThumb.item(0)).getNodeValue());
				thumbnail += (j == mediaList.getLength() - 1) ? thumbnailFilename
						.getName() : thumbnailFilename.getName()
						+ ",";
			 }
			 
		 }
		 thumbnail = resource.getString("resourceid");;
		 incidentData.setIncidentThumbnail(thumbnail);

		 image = resource.getString("resourceid");;
		 incidentData.setIncidentImage(image);
		 /////////////////////////////////
		  
		  
		incidentData.setIncidentVerified(resource
		        .getInt("resourceverified"));

		incidentData.setIncidentLocLatitude(resource
		        .getString("locationlatitude"));

		incidentData.setIncidentLocLongitude(resource
		        .getString("locationlongitude"));

	    }
	}
	catch (JSONException e)
	{
	    tmpResourcesPile.clear();// by OceanMaster
	    Log.v("Oceanmaster",
		    "ERROR occured during Processing in Around Me Page");
	}

	return tmpResourcesPile;
	/*
	 * Cursor cursor = UshahidiApplication.mDb.fetchNearByResources(
	 * holder_latitude, holder_longitude, 0.5);
	 * 
	 * String title; String description; String location; String categories;
	 * String thumbnail; String image;
	 * 
	 * if (cursor.moveToFirst()) { tmpResourcesPile.clear();// by
	 * OceanMaster
	 * 
	 * int idIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_ID); int titleIndex
	 * = cursor .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_TITLE); int
	 * dateIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_DATE); int
	 * verifiedIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_VERIFIED); int
	 * locationIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_LOC_NAME);
	 * 
	 * int descIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_DESC);
	 * 
	 * int categoryIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_CATEGORIES);
	 * 
	 * int mediaIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_MEDIA);
	 * 
	 * int imageIndex = cursor
	 * .getColumnIndex(UshahidiDatabase.RESOURCE_IMAGE);
	 * 
	 * int latitudeIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_LOC_LATITUDE);
	 * 
	 * int longitudeIndex = cursor
	 * .getColumnIndexOrThrow(UshahidiDatabase.RESOURCE_LOC_LONGITUDE);
	 * 
	 * do {
	 * 
	 * IncidentsData incidentData = new IncidentsData();
	 * tmpResourcesPile.add(incidentData);
	 * 
	 * int id = Util.toInt(cursor.getString(idIndex));
	 * incidentData.setIncidentId(id);
	 * 
	 * title = Util.capitalizeString(cursor.getString(titleIndex));
	 * incidentData.setIncidentTitle(title);
	 * 
	 * description = cursor.getString(descIndex);
	 * incidentData.setIncidentDesc(description);
	 * 
	 * categories = cursor.getString(categoryIndex);
	 * incidentData.setIncidentCategories(categories);
	 * 
	 * location = cursor.getString(locationIndex);
	 * incidentData.setIncidentLocLongitude(location);
	 * 
	 * Util.joinString("Date: ", cursor.getString(dateIndex));
	 * incidentData.setIncidentDate(cursor.getString(dateIndex));
	 * 
	 * thumbnail = cursor.getString(mediaIndex);
	 * incidentData.setIncidentThumbnail(thumbnail);
	 * 
	 * image = cursor.getString(imageIndex);
	 * incidentData.setIncidentImage(image);
	 * 
	 * incidentData.setIncidentVerified(Util.toInt(cursor
	 * .getString(verifiedIndex)));
	 * 
	 * incidentData.setIncidentLocLatitude(cursor
	 * .getString(latitudeIndex));
	 * incidentData.setIncidentLocLongitude(cursor
	 * .getString(longitudeIndex)); Log.v("Oceanmaster",
	 * "One Row: lat = "+incidentData.getIncidentLocLatitude()
	 * +" , long = "+
	 * incidentData.getIncidentLocLongitude()+" , category = "+categories);
	 * } while (cursor.moveToNext()); } cursor.close(); return
	 * tmpResourcesPile;
	 
    }*/

    /********************
     * Main Life Cycle OceanMaster
     ********************/

    @Override
    public void onResume()
    {
	Log.v("Oceanmaster", "Around Me Resumed");
	GPSCount = 0;
	readyLocationService();
	super.onResume();
    }

    @Override
    protected void onDestroy()
    {
	unregisterListeners();
	// GPSUpdated = false;
	super.onDestroy();
    }

    @Override
    protected void onPause()
    {
    AroundMe.ResourcesInMapView=tmpResourcesPile; // set tabhost so that map and list are with the same data
	unregisterListeners();
	// GPSUpdated = false;
	// SharedPreferences.Editor editor = getPreferences(0).edit();
	// editor.putString("title", mIncidentTitle.getText().toString());
	// editor.putString("desc", mIncidentDesc.getText().toString());
	// editor.putString("location", mIncidentLocation.getText().toString());
	// editor.commit();
	super.onPause();
    }

    @Override
    protected void onStop()
    {
	unregisterListeners();
	// GPSUpdated = false;
	super.onStop();
    }

    /********************
     * Data Fetching
     ********************/

    // double MinDistance = 0.001; // In degree
    //
    // public boolean farEnoughToUpdate()
    // {
    // return (Math.abs(old_holder_latitude - holder_latitude)
    // + Math.abs(old_holder_longitude - holder_longitude) > MinDistance);
    // }
    //
    // static double old_holder_latitude;
    // static double old_holder_longitude;

    // IMPORTANT!!!
    // Assume updateNearBy will only be called by Location Listener.
    // So latitude and longitude is updated.
    GeoPoint position;

    private void updateNearBy()
    {
	GPSCount = (GPSCount + 1) % updateCycle;

	// Update 'me' position
	position = getPoint(holder_latitude, holder_longitude);

	if (me == null)
	{
	    me = new MapMarker(markers.get(0), position.getLatitudeE6(),
		    position.getLongitudeE6());
	    mapView.getOverlays().add(me);
	}
	else
	    me.updateLocation(position.getLatitudeE6(),
		    position.getLongitudeE6());

	if (GPSCount != 1)
	    return;
	// Update nearby position

	// Judge if it is necessary to update
	// if (farEnoughToUpdate())
	// {
	// old_holder_latitude = holder_latitude;
	// old_holder_longitude = holder_longitude;
	// }
	// else
	// {
	// return;
	// }
	NearbyResources = QueryNearBy();
	if (NearbyResources != null && NearbyResources.size() > 0)
	{
	    ClearMap();
	    // TODO to be changed according to user range
	    // mapView.getController().setZoom(5);
	    mHandler.post(mMarkersOnMap);
	    // Draw Markers on Map
	}
	else
	{
	    //Toast.makeText(AroundMeMap.this,"There are no resources in selected range",Toast.LENGTH_LONG).show();
	    ClearMap();
	    mHandler.post(mMarkersOnMap);
	    Util.showToast(AroundMeMap.this, "No resources in selected range");
	}
    }

    /********************
     * Geo Location related function OceanMaster
     ********************/
    LocationManager                                      manager;
    long                                                 updateTimeMsec = 1000;
    float                                                updateDistance = 0;
    LocationProvider                                     high;
    LocationProvider                                     low;
    private HighSensitiveMultiTimeDeviceLocationListener high_listener  = null;
    private LowSensitiveOneTimeDeviceLocationListener    low_listener   = null;

    private void registerHighOneTimeListener()
    {
	high_listener = new HighSensitiveMultiTimeDeviceLocationListener();
	manager.requestLocationUpdates(high.getName(), updateTimeMsec,
	        updateDistance, high_listener);
    }

    private void registerLowOneTimeListener()
    {
	low_listener = new LowSensitiveOneTimeDeviceLocationListener();
	manager.requestLocationUpdates(low.getName(), 100, updateDistance,
	        low_listener);
    }

    private void unregisterListeners()
    {
	if (high_listener != null)
	{
	    manager.removeUpdates(high_listener);
	    high_listener = null;
	}
	if (low_listener != null)
	{
	    manager.removeUpdates(low_listener);
	    low_listener = null;
	}
    }

    // Fetches the current location of the device.
    // create two different listeners, one for once, one for long
    // temporarily, periodical location service is not needed because
    // we are not following user
    private void readyLocationService()
    {
	Log.v("Oceanmaster", "Ready Location Service");
	// ===============================
	// ready one time location request
	// ===============================
	// listener = new OneTimeDeviceLocationListener();
	manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

	// get low and high accuracy provider
	// this is tempararily changed, due to simulation
	//low = manager.getProvider(manager.getBestProvider(Util.createCoarseCriteria(), true));
	//high = manager.getProvider(manager.getBestProvider(Util.createFineCriteria(), true));
	low = manager.getProvider(manager.NETWORK_PROVIDER);
	high = manager.getProvider(manager.GPS_PROVIDER);

	// imediately register 2 one time service to update location
	unregisterListeners();
	registerHighOneTimeListener();
	registerLowOneTimeListener();
    }

    public GeoPoint getPoint(double lat, double lon)
    {
	return (new GeoPoint((int) (lat * 1000000.0), (int) (lon * 1000000.0)));
    }

    // get the current location of the device/user
    public class LowSensitiveOneTimeDeviceLocationListener implements
	    LocationListener
    {
	LowSensitiveOneTimeDeviceLocationListener()
	{
	    super();
	    Log.v("Oceanmaster", "new OneTimeListener Created");
	}

	public void onLocationChanged(Location location)
	{
	    if (location != null&&!mapmoved)
	    {
		manager.removeUpdates(LowSensitiveOneTimeDeviceLocationListener.this);
		mapmoved=true;
		mapView.postInvalidate();
		// GPSUpdated = true;

		// this function shall be abandoned some day....
		// don't count here

		holder_latitude = location.getLatitude();
		holder_longitude = location.getLongitude();
		Log.v("Oceanmaster", "Location Changed : " + holder_latitude
		        + " , " + holder_longitude);
		centerLocation(getPoint(holder_latitude, holder_longitude));
		updateNearBy();
		GPSCount--;
		
		// mReportLocation.setText(String.valueOf(holder_latitude) +
		// ", " + String.valueOf(holder_longitude));
	    }
	}

	public void onProviderDisabled(String provider)
	{
	    // Util.showToast(AroundMeMap.this, R.string.location_not_found);
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Disabled");
	}

	public void onProviderEnabled(String provider)
	{
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Enabled");
	}

	public void onStatusChanged(String provider, int status, Bundle extras)
	{
	}
    }

    public class HighSensitiveMultiTimeDeviceLocationListener implements
	    LocationListener
    {
	HighSensitiveMultiTimeDeviceLocationListener()
	{
	    super();
	    Log.v("Oceanmaster", "new MultiTimeListener Created");
	}

	public void onLocationChanged(Location location)
	{
	    if (location != null&&!mapmoved)
	    {
		// GPSUpdated = true;
	    mapmoved=true;
	    mapView.postInvalidate();
		holder_latitude = location.getLatitude();
		holder_longitude = location.getLongitude();

		Log.v("Oceanmaster", "Location Changed : " + holder_latitude
		        + " , " + holder_longitude);
		if (follow)
		    centerLocation(getPoint(holder_latitude, holder_longitude));
		updateNearBy();
		// mReportLocation.setText(String.valueOf(holder_latitude) +
		// ", " + String.valueOf(holder_longitude));
		// Need to solve problem: Me position covers each other!!
	    }
	}

	public void onProviderDisabled(String provider)
	{
	    Util.showToast(
		    AroundMeMap.this,
		    "GPS service is disabled due to Configuration or Low signal strength, please check your setting or go near the window.");
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Disabled");
	}

	public void onProviderEnabled(String provider)
	{
	    Util.showToast(AroundMeMap.this, "GPS service recover.");
	    Log.v("Oceanmaster", "LocationProvider " + provider.toString()
		    + " Enabled");
	}

	public void onStatusChanged(String provider, int status, Bundle extras)
	{

	}
    }

    /********************
     * Tasks OceanMaster
     ********************/
    // The thread to populate map
    final Runnable mMarkersOnMap = new Runnable()
	                         {
	                             public void run()
	                             {
		                         drawNearByMap();
	                             }
	                         };

    private class QueryTask extends AsyncTask<Void, Void, Integer>
    {

	protected Integer status;
	protected Context appContext;

	@Override
	protected void onPreExecute()
	{
	    setProgressBarIndeterminateVisibility(true);
	}

	@Override
	protected Integer doInBackground(Void... params)
	{
	    status = Util.processReports(appContext);
	    return status;
	}

	// OceanMaster: onPost... is checking the number returned by doIn...

	@Override
	protected void onPostExecute(Integer result)
	{
	    if (result == 4)
	    {
		Util.showToast(appContext, R.string.internet_connection);
	    }
	    else if (result == 0)
	    {
		NearbyResources = QueryNearBy();
		drawNearByMap();
		setProgressBarIndeterminateVisibility(false);
	    }
	}
    }

    /********************
     * Draw Map related OceanMaster
     ********************/
    MapMarker me = null; // The Marker denotes 'me'

    private void ClearMap()
    {
	mapView.getOverlays().clear();
    }

    // 0: me
    // 1: hospital
    // 2: shelter
    // 3: water
    // 4: food
    // 5: heavy equipment
    // 6: generic
    public void LoadMarkers()
    {
	// Oceanmaster
	// ------------------------
	// Load Icons
	// ------------------------
	markers = new ArrayList<Drawable>();

	Drawable marker;

	marker = getResources().getDrawable(R.drawable.me);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_hospital);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_shelter);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_drinking_water);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_food);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_heavy_equipment);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);

	marker = getResources().getDrawable(R.drawable.icon_generic);
	marker.setBounds(0, 0, marker.getIntrinsicWidth(),
	        marker.getIntrinsicHeight());
	markers.add(marker);
    }

    // add markers to the map
    private void drawNearByMap()
    {
	// GeoPoint position;
	// int iconindex = 0;

	// 1:Mark self on map
	// there is a clear map above
	// position = getPoint(holder_latitude, holder_longitude);
	// PlaceSingleMarker(position.getLatitudeE6(),
	// position.getLongitudeE6(),0);
	if (me == null)
	    me = new MapMarker(markers.get(0), position.getLatitudeE6(),
		    position.getLongitudeE6());
	else
	    me.updateLocation(position.getLatitudeE6(),
		    position.getLongitudeE6());
	mapView.getOverlays().add(me);

	// 2:Others
	// Approach 1:
	/*
	 * if (false) for (IncidentsData data : NearbyResources) { position =
	 * getPoint( Double.parseDouble(data.getIncidentLocLatitude()),
	 * Double.parseDouble(data.getIncidentLocLongitude())); String cates =
	 * data.getIncidentCategories();
	 * 
	 * if (cates.contains("Hospital")) iconindex = 1; else if
	 * (cates.contains("Shelter")) iconindex = 2; else if
	 * (cates.contains("Water")) iconindex = 3; else iconindex = 4;
	 * 
	 * PlaceSingleMarker(position.getLatitudeE6(),
	 * position.getLongitudeE6(), iconindex); Log.v("Oceanmaster",
	 * "New mark should be placed, type = " + iconindex); }
	 * 
	 * // Approcah 2 TODO else {
	 */
	// Me
	// Hospital
	List<IncidentsData> hospital = new ArrayList<IncidentsData>();
	// Shelter
	List<IncidentsData> shelter = new ArrayList<IncidentsData>();
	// Water
	List<IncidentsData> water = new ArrayList<IncidentsData>();
	// Food
	List<IncidentsData> food = new ArrayList<IncidentsData>();
	// Heavy equipments
	List<IncidentsData> equip = new ArrayList<IncidentsData>();
	// Generc
	List<IncidentsData> generic = new ArrayList<IncidentsData>();

	for (IncidentsData data : NearbyResources)
	{
	    String cates = data.getIncidentCategories();

	    if (cates.contains("Hospital"))
	    {
		hospital.add(data);
		continue;
	    }
	    else if (cates.contains("Temporary Shelter"))
	    {
		shelter.add(data);
		continue;
	    }
	    else if (cates.contains("Drinking Water"))
	    {
		water.add(data);
		continue;
	    }
	    else if (cates.contains("Food"))
	    {
		food.add(data);
		continue;
	    }
	    else if (cates.contains("Heavy Equipment"))
	    {
		equip.add(data);
		continue;
	    }

	    else
		generic.add(data);
	}

	if (hospital.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, hospital, 1));
	if (shelter.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, shelter, 2));
	if (water.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, water, 3));
	if (food.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, food, 4));
	if (equip.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, equip, 5));
	if (generic.size() > 0)
	    mapView.getOverlays().add(new SitesOverlay(mapView, generic, 6));

	Log.v("Oceanmaster",
	        "Populate Marker Over; Hospitals:" + hospital.size()
	                + " shelters:" + shelter.size() + " water:"
	                + water.size() + " food:" + food.size()
	                + " equipments:" + equip.size() + " others:"
	                + generic.size());
	/* } */
	
	// 3: Mark the circle
	mapView.getOverlays().add(new CircleOverlay(this, holder_latitude,holder_longitude));
    }

    private void PlaceSingleMarker(int markerLatitude, int markerLongitude,
	    int iconindex)
    {
	// mapView.getOverlays().clear();
	me = new MapMarker(markers.get(iconindex), markerLatitude,
	        markerLongitude);
	mapView.getOverlays().add(me);
    }

    // Modified by OceanMaster, added updateText argument
    private void centerLocation(GeoPoint centerGeoPoint)
    {
	mapView.getController().animateTo(centerGeoPoint);
	// latitude = centerGeoPoint.getLatitudeE6() / 1.0E6;
	// longitude = centerGeoPoint.getLongitudeE6() / 1.0E6;
	// if (updateText)
	// mIncidentLocation.setText(getLocationFromLatLon(latitude,longitude));
	// PlaceSingleMarker(centerGeoPoint.getLatitudeE6(),centerGeoPoint.getLongitudeE6(),0);
    }

    private void setLocationBySearch(String search)
    {
	Log.v("Oceanmaster", "setLocationBySearch : " + search);
	if (search == null || search.length() == 0)
	{
	    Util.showToast(AroundMeMap.this,
		    "Please fill search field first to find location");
	    return;
	}
	try
	{
	    List<Address> result = mGc.getFromLocationName(search, 1);
	    if (result.size() <= 0)
	    {
		Util.showToast(AroundMeMap.this, "No result found");
		return;
	    }

	    Address location = result.get(0);

	    latitude = location.getLatitude();
	    longitude = location.getLongitude();

	    centerLocation(getPoint(latitude, longitude));
	    // mReportLocation.setText(String.valueOf(latitude) + ", " +
	    // String.valueOf(longitude));

	}
	catch (IOException e)
	{
	    Util.showToast(AroundMeMap.this,
		    "Error occured while trying to search Location");
	}
    }

    private List<Address> mFoundAddresses;

    // get the real location name from the latitude and longitude.
    private String getLocationFromLatLon(double lat, double lon)
    {
	Log.v("Oceanmaster", "Location name service requested");
	try
	{
	    Address address;
	    mFoundAddresses = mGc.getFromLocation(lat, lon, 2);
	    if (mFoundAddresses.size() > 0)
	    {
		address = mFoundAddresses.get(0);
		return address.getSubAdminArea();
	    }
	    else
	    {
		return "";
	    }
	}
	catch (IOException e)
	{
	    e.printStackTrace();
	}
	return "";
    }

    public class MapMarker extends ItemizedOverlay<OverlayItem>
    {

	private List<OverlayItem> locations = new ArrayList<OverlayItem>();

	private Drawable          marker;

	private OverlayItem       myOverlayItem;

	public MapMarker(Drawable defaultMarker, int LatitudeE6, int LongitudeE6)
	{
	    super(defaultMarker);
	    this.marker = defaultMarker;

	    // create locations of interest
	    GeoPoint myPlace = new GeoPoint(LatitudeE6, LongitudeE6);

	    myOverlayItem = new OverlayItem(myPlace, " ", " ");

	    locations.add(myOverlayItem);

	    populate();

	}

	// Added by OceanMaster, not tested
	public void updateLocation(int LatitudeE6, int LongitudeE6)
	{
	    locations.clear();
	    GeoPoint myPlace = new GeoPoint(LatitudeE6, LongitudeE6);
	    myOverlayItem = new OverlayItem(myPlace, " ", " ");
	    locations.add(myOverlayItem);
	    populate();
	}

	// Added by OceanMaster, not tested
	public void addLocation(int LatitudeE6, int LongitudeE6)
	{
	    GeoPoint myPlace = new GeoPoint(LatitudeE6, LongitudeE6);
	    myOverlayItem = new OverlayItem(myPlace, " ", " ");
	    locations.add(myOverlayItem);
	    populate();
	}

	@Override
	protected OverlayItem createItem(int i)
	{
	    return locations.get(i);
	}

	@Override
	public int size()
	{
	    return locations.size();
	}

	@Override
	public void draw(Canvas canvas, MapView mapView, boolean shadow)
	{
	    super.draw(canvas, mapView, shadow);
	    // TODO
	    // Changed by OceanMaster!
	    // New icon is not bottom_centered
	    boundCenter(marker);
	    // boundCenterBottom(marker);
	}
    }

    private class SitesOverlay extends UshahidiItemizedOverlay<OverlayItem>
    {
	private ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();

	public SitesOverlay(MapView mapView, List<IncidentsData> Resources,
	        int iconindex)
	{
	    // changed from boundCenterBottom to boundCenter
	    super(boundCenter(markers.get(iconindex)), mapView,
		    AroundMeMap.this, Resources, extras,true);
	    mapView.getContext();

	    for (IncidentsData resourceData : Resources)
	    {
		AroundMeMap.latitude = Double.parseDouble(resourceData
		        .getIncidentLocLatitude());
		AroundMeMap.longitude = Double.parseDouble(resourceData
		        .getIncidentLocLongitude());

		items.add(new OverlayItem(getPoint(AroundMeMap.latitude,
		        AroundMeMap.longitude),
		        resourceData.getIncidentTitle(), Util.limitString(
		                resourceData.getIncidentDesc(), 30)));
	    }

	    populate();
	}

	@Override
	protected OverlayItem createItem(int i)
	{
	    return items.get(i);
	}

	@Override
	protected boolean onBalloonTap(int i)
	{
	    return true;
	}

	@Override
	public int size()
	{
	    return (items.size());
	}
    }

    
    
    
    
    public class CircleOverlay extends Overlay
    {
	Context context;
	double  mLat;
	double  mLon;

	public CircleOverlay(Context _context, double _lat, double _lon)
	{
	    context = _context;
	    mLat = _lat;
	    mLon = _lon;
	}

	public void draw(Canvas canvas, MapView mapView, boolean shadow)
	{
	    super.draw(canvas, mapView, shadow);
	    Projection projection = mapView.getProjection();
	    Point pt = new Point();
	    GeoPoint geo = new GeoPoint((int) (mLat * 1e6), (int) (mLon * 1e6));
	    projection.toPixels(geo, pt);
	    float circleRadius = 150;
	    Paint innerCirclePaint;
	    innerCirclePaint = new Paint();
	    innerCirclePaint.setARGB(16, 0, 0, 255);	//transparent blue
	    innerCirclePaint.setAntiAlias(true);
	    innerCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
	    canvas.drawCircle((float) pt.x, (float) pt.y, circleRadius,
		    innerCirclePaint);
	}
    }

    /********************
     * Ordinary stuff OceanMaster
     ********************/
    @Override
    protected void onActivityResult(int requestCode, int resultCode,
	    Intent intent)
    {
	super.onActivityResult(requestCode, resultCode, intent);
    }

    // menu stuff
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
	    ContextMenu.ContextMenuInfo menuInfo)
    {
	populateMenu(menu);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
	populateMenu(menu);

	return (super.onCreateOptionsMenu(menu));
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item)
    {
	// applyMenuChoice(item);

	return (applyMenuChoice(item) || super.onOptionsItemSelected(item));
    }

    @Override
    public boolean onContextItemSelected(MenuItem item)
    {

	return (applyMenuChoice(item) || super.onContextItemSelected(item));
    }

    protected Dialog onCreateDialog(int id, String message, String title)
    {
	switch (id)
	{
	    case DIALOG_MESSAGE:
	    {
		AlertDialog dialog = (new AlertDialog.Builder(this)).create();
		dialog.setTitle(title);
		dialog.setMessage(message);
		dialog.setButton2("Ok", new Dialog.OnClickListener()
		{
		    public void onClick(DialogInterface dialog, int which)
		    {
			dialog.dismiss();
		    }
		});
		dialog.setCancelable(false);
		return dialog;
	    }
	}
	return null;
    }

    private void populateMenu(Menu menu)
    {
	MenuItem i;
	i = menu.add(Menu.NONE, HOME, Menu.NONE, R.string.menu_home);
	i.setIcon(R.drawable.ushahidi_home);

	i = menu.add(Menu.NONE, INCIDENT_ADD, Menu.NONE,
	        R.string.incident_menu_add);
	i.setIcon(R.drawable.ushahidi_add);

	i = menu.add(Menu.NONE, LIST_INCIDENT, Menu.NONE,
	        R.string.incident_list);
	i.setIcon(R.drawable.ushahidi_list);

	i = menu.add(Menu.NONE, INCIDENT_REFRESH, Menu.NONE,
	        R.string.incident_menu_refresh);
	i.setIcon(R.drawable.ushahidi_refresh);

	i = menu.add(Menu.NONE, SETTINGS, Menu.NONE, R.string.menu_settings);
	i.setIcon(R.drawable.ushahidi_settings);

	i = menu.add(Menu.NONE, ABOUT, Menu.NONE, R.string.menu_about);
	i.setIcon(R.drawable.ushahidi_about);

    }

    private boolean applyMenuChoice(MenuItem item)
    {
	Intent intent;
	switch (item.getItemId())
	{
	    case HOME:
		intent = new Intent(AroundMeMap.this, Ushahidi.class);
		startActivityForResult(intent, GOTOHOME);
		return true;
	    case INCIDENT_REFRESH:
		QueryTask queryTask = new QueryTask();
		queryTask.appContext = this;
		queryTask.execute();
		return (true);

	    case LIST_INCIDENT:
		extras = new Bundle();
		extras.putInt("tab_index", 0);
		intent = new Intent(AroundMeMap.this, IProvide.class);
		intent.putExtra("tab", extras);
		startActivityForResult(intent, LIST_INCIDENTS);
		return (true);

	    case INCIDENT_ADD:
		intent = new Intent(AroundMeMap.this, AddIncident.class);
		startActivityForResult(intent, ADD_INCIDENTS);
		return (true);

	    case ABOUT:
		intent = new Intent(AroundMeMap.this, About.class);
		startActivityForResult(intent, REQUEST_CODE_ABOUT);
		setResult(RESULT_OK);
		return true;

	    case SETTINGS:
		intent = new Intent(AroundMeMap.this, Settings.class);
		// Make it a subactivity so we know when it returns
		startActivityForResult(intent, REQUEST_CODE_SETTINGS);
		return (true);
	}
	return false;
    }
}
